'''
Created on 3.11.2011

@author: halldor
'''
from datetime import date
from datetime import timedelta

class DateRollingConvention(object):
    '''
    Enum class for date rolling convention
    Parameters: 
        actual
        following
        modifiedfollowing
        preceding
        modifiedpreceding
    Returns:
    '''
    (actual, following, modifiedfollowing, preceding, modifiedpreceding) = range(5)

def modifiedfollowing(caldar, ddate):
    '''
    Modified following business day. The payment date is rolled to the next business day, 
    unless doing so would cause the payment to be in the next calendar month, in which case 
    the payment date is rolled to the preceding business day.
    Parameters:
        date
    Returns: 
        date according to modified following business day convention 
    '''
    if caldar.isBusinessDay(ddate) == False:
        newdate = ddate + timedelta(days=1)
        if newdate.month != ddate.month:
            return preceding(caldar, ddate)
        return modifiedfollowing(caldar, newdate)
    else:
        return ddate

def modifiedpreceding(caldar, ddate):
    '''
    Modified preceding business day. The payment date is rolled to the preceding business day, 
    unless doing so would cause the payment to be in the previous calendar month, in which case 
    the payment date is rolled to the next business day. 
    Parameters:
        date
    Returns: 
        date according to modified preceding business day convention 
    '''
    if caldar.isBusinessDay(ddate) == False:
        newdate = ddate + timedelta(days=-1)
        if newdate.month != ddate.month:
            return following(caldar, ddate)
        return modifiedpreceding(caldar, newdate)
    else:
        return ddate

def following(caldar, ddate):
    '''
    The payment date is rolled to the next business day.
    Parameters:
        date
    Returns: 
        date according to following business day convention 
    '''
    if caldar.isBusinessDay(ddate) == False:
        newdate = ddate + timedelta(days=1)
        return following(caldar, newdate)
    else:
        return ddate

def preceding(caldar, ddate):
    '''
    The payment date is rolled to the previous business day.
    Parameters:
        date
    Returns: 
        date according to previous business day convention 
    '''
    if caldar.isBusinessDay(ddate) == False:
        newdate = ddate + timedelta(days=-1)
        return preceding(caldar, newdate)
    else:
        return ddate
